package main

import (

	"fmt"
	"net"
	"os"
	"strconv"
	"time"
	"runtime"
	"os/signal"
	"crypto/md5"
	"morego_go_client/protocol"

)

//var Conns = make([]*net.TCPConn, 1000)

func createReqConns(num int64) []*net.TCPConn{

	var conns []*net.TCPConn
	conns = make([]*net.TCPConn, 0, num)

	for i := 0; i < int(num); i++ {
		service := os.Args[1]
		tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
		if err != nil {
			fmt.Println(err.Error())
		}
		conn, err := net.DialTCP("tcp", nil, tcpAddr)
		defer conn.Close()
		conns=append( conns,conn)
	}
	return conns

} //

func getReqStrData(num int64) string {

	data := ""

	type_ := protocol.TypeReq
	cmd := "user.getUser"
	req_data := time.Now().Unix()
	srcData := "1" // []byte( strconv.FormatInt(time.Now().Unix(), 10) )
	sid := md5.Sum([]byte(srcData))
	req_id := num
	data = fmt.Sprintf("%d||%s||%x||%d||%d", type_, cmd, sid, req_id, req_data)

	return data

}   //

func main() {

	runtime.GOMAXPROCS(runtime.NumCPU())
	start:=time.Now().Unix()
	if len(os.Args) < 4 {
		fmt.Fprintf(os.Stderr, "Usage:%s  host:port connections send_times packet_type ", os.Args[0])
		os.Exit(1)
	}
	//go end_hook( start )
	packet_type := "str"
	if( len(os.Args)>4 ){
		packet_type =  string( os.Args[4] )
	}
	fmt.Println( " packet_type : ", packet_type )

	times, _ := strconv.ParseInt(os.Args[3], 10, 32)
	conn_num, _ := strconv.ParseInt(os.Args[2], 10, 32)
	fmt.Println( "Connections and  times:", conn_num, times )

	//conns:=createReqConns(conn_num)
	ch_success := make(chan int64 ,0)

	var i int64

	for i = 0; i < conn_num; i++ {
		service := os.Args[1]
		tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
		if err != nil {
			fmt.Println(err.Error())
		}
		conn, err := net.DialTCP("tcp", nil, tcpAddr)

		go func(conn2 *net.TCPConn ,times int64) {
			//time.Sleep(time.Duration(1) * time.Second)
			data:=getReqStrData(conn_num)
			var j int64
			buf := append([]byte(data), '\n')
			var success int64;
			success=0
			fmt.Println( " times:", times )
			for j = 0; j < times; j++ {
				_, err := conn2.Write(buf)
				//time.Sleep(10 * time.Millisecond)
				if err != nil {
					fmt.Println("send err:", err.Error())
					continue
				}
				//fmt.Println("send size:", n)
				success++
			}
			fmt.Println("success times:",success)
			ch_success<-success
			conn2.Close()

			return


		}( conn ,times  )
	}

	var qps int64
	qps=0
	for  i = 0; i < conn_num; i++   {
		select {
		case r := <-ch_success:
			fmt.Println("r:", r )
			qps = qps+r
		default:
			fmt.Printf(".")
			end := time.Now().Unix()
			els_time := end - start
			fmt.Println("time:", els_time, qps )
			time.Sleep(1000 * time.Millisecond)
		}
	}

}


func checkError(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
		os.Exit(1)
	}
}

func end_hook(start int64) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	s := <-c
	end := time.Now().Unix()
	els_time := end - start
	fmt.Println("Got signal:", s)
	fmt.Println("need time :", els_time)
	os.Exit(1)

}
